﻿// -----------------------------------------------------------------------
// <copyright file="PerformanceRunner.cs" company="Home">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using IocPerformance.Classes.Generics;
using My.Ioc.Extensions.OpenGeneric;

namespace IocPerformance
{
    using My.Ioc;
    using IocPerformance.Classes.Complex;
    using IocPerformance.Classes.Dummy;
    using IocPerformance.Classes.Multiple;
    using IocPerformance.Classes.Standard;
    using NLite.Test;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class PerformanceRunner
    {
        bool _init;
        const int LoopTimes = 5000000;
        IObjectContainer _container;

        public void AllInOneTest()
        {
            if (!_init)
                Init();
            CodeTimer.Time("AllInOneTest", AllInOne);
        }

        public void SingletonTest()
        {
            if (!_init)
                Init();
            CodeTimer.Time("SingletonTest", Singleton);
        }

        public void TransientTest()
        {
            if (!_init)
                Init();
            CodeTimer.Time("TransientTest", Transient);
        }

        public void CombinedTest()
        {
            if (!_init)
                Init();
            CodeTimer.Time("CombinedTest", Combined);
        }

        public void ComplexTest()
        {
            if (!_init)
                Init();
            CodeTimer.Time("ComplexTest", Complex);
        }

        void AllInOne()
        {
            for (int i = 0; i < LoopTimes; i++)
            {
                var result1 = _container.Resolve<ISingleton>();
                var result2 = _container.Resolve<ITransient>();
                var result3 = _container.Resolve<ICombined>();
                var complexResult = _container.Resolve<IComplex>();
            }
        }

        void Singleton()
        {
            for (int i = 0; i < LoopTimes; i++)
            {
                var result1 = _container.Resolve<ISingleton>();
            }
        }

        void Transient()
        {
            for (int i = 0; i < LoopTimes; i++)
            {
                var result2 = _container.Resolve<ITransient>();
            }
        }

        void Combined()
        {
            for (int i = 0; i < LoopTimes; i++)
            {
                var result3 = _container.Resolve<ICombined>();
            }
        }

        void Complex()
        {
            for (int i = 0; i < LoopTimes; i++)
            {
                var complexResult = _container.Resolve<IComplex>();
            }
        }

        void Init()
        {
            _container = new ObjectContainer(true);
            RegisterDummies(_container);
            RegisterStandard(_container);
            RegisterComplexObject(_container);
            RegisterOpenGeneric(_container);
            RegisterMultiple(_container);
            _init = true;
        }

        private static void RegisterDummies(IObjectContainer container)
        {
            container.Register<IDummyOne, DummyOne>();
            container.Register<IDummyTwo, DummyTwo>();
            container.Register<IDummyThree, DummyThree>();
            container.Register<IDummyFour, DummyFour>();
            container.Register<IDummyFive, DummyFive>();
            container.Register<IDummySix, DummySix>();
            container.Register<IDummySeven, DummySeven>();
            container.Register<IDummyEight, DummyEight>();
            container.Register<IDummyNine, DummyNine>();
            container.Register<IDummyTen, DummyTen>();
        }

        private static void RegisterStandard(IObjectContainer container)
        {
            container.Register<ISingleton, Singleton>().In(Lifetime.Container());
            container.Register<ITransient, Transient>();
            container.Register<ICombined, Combined>();
        }

        private static void RegisterComplexObject(IObjectContainer container)
        {
            container.Register<IFirstService, FirstService>().In(Lifetime.Container());
            container.Register<ISecondService, SecondService>().In(Lifetime.Container());
            container.Register<IThirdService, ThirdService>().In(Lifetime.Container());
            container.Register<ISubObjectOne, SubObjectOne>();
            container.Register<ISubObjectTwo, SubObjectTwo>();
            container.Register<ISubObjectThree, SubObjectThree>();
            container.Register<IComplex, Complex>();
        }

        private static void RegisterMultiple(IObjectContainer container)
        {
            container.Register<ISimpleAdapter, SimpleAdapterOne>();
            container.Register<ISimpleAdapter, SimpleAdapterTwo>();
            container.Register<ISimpleAdapter, SimpleAdapterThree>();
            container.Register<ISimpleAdapter, SimpleAdapterFour>();
            container.Register<ISimpleAdapter, SimpleAdapterFive>();
            container.Register<ImportMultiple, ImportMultiple>();
        }

        private static void RegisterOpenGeneric(IObjectContainer container)
        {
            container.RegisterOpenGeneric(typeof(IGenericInterface<>), typeof(GenericExport<>));
            container.RegisterOpenGeneric(typeof(ImportGeneric<>), typeof(ImportGeneric<>));
        }
    }
}
